#include "AsyncClient.hpp"

#include "ESPAsyncWebServer.h"
#include "WebResponseImpl.h"

#define TAG "WebResponses"

/// @brief 将HTTP状态码转化为字符串
/// @param code HTTP状态码
/// @return
const char* AsyncWebServerResponse::m_responseCodeToString(int code)
{
    switch (code) {
    case 100: return "Continue";
    case 101: return "Switching Protocols";
    case 200: return "OK";
    case 201: return "Created";
    case 202: return "Accepted";
    case 203: return "Non-Authoritative Information";
    case 204: return "No Content";
    case 205: return "Reset Content";
    case 206: return "Partial Content";
    case 300: return "Multiple Choices";
    case 301: return "Moved Permanently";
    case 302: return "Found";
    case 303: return "See Other";
    case 304: return "Not Modified";
    case 305: return "Use Proxy";
    case 307: return "Temporary Redirect";
    case 400: return "Bad Request";
    case 401: return "Unauthorized";
    case 402: return "Payment Required";
    case 403: return "Forbidden";
    case 404: return "Not Found";
    case 405: return "Method Not Allowed";
    case 406: return "Not Acceptable";
    case 407: return "Proxy Authentication Required";
    case 408: return "Request Time-out";
    case 409: return "Conflict";
    case 410: return "Gone";
    case 411: return "Length Required";
    case 412: return "Precondition Failed";
    case 413: return "Request Entity Too Large";
    case 414: return "Request-URI Too Large";
    case 415: return "Unsupported Media Type";
    case 416: return "Requested range not satisfiable";
    case 417: return "Expectation Failed";
    case 500: return "Internal Server Error";
    case 501: return "Not Implemented";
    case 502: return "Bad Gateway";
    case 503: return "Service Unavailable";
    case 504: return "Gateway Time-out";
    case 505: return "HTTP Version not supported";
    default:  return "";
    }
}

AsyncWebServerResponse::AsyncWebServerResponse()
    : m_code(0)
    , m_headers(LinkedList<AsyncWebHeader*>([](AsyncWebHeader * h)
{
    delete h;
}))
, m_contentType()
, m_contentLength(0)
, m_sendContentLength(true)
, m_chunked(false)
, m_headLength(0)
, m_sentLength(0)
, m_ackedLength(0)
, m_writtenLength(0)
, m_state(RESPONSE_SETUP)
{
    // 添加默认头部信息
    for (auto header : DefaultHeaders::Instance()) {
        m_headers.add(new AsyncWebHeader(header->name(), header->value()));
    }
}

AsyncWebServerResponse::~AsyncWebServerResponse()
{
    m_headers.free();
}

/// @brief 在RESPONSE_SETUP阶段设置HTTP响应码（其他阶段无效）
/// @param code
void AsyncWebServerResponse::setCode(int code)
{
    if (m_state == RESPONSE_SETUP) {
        m_code = code;
    }
}

/// @brief 在RESPONSE_SETUP阶段设置响应内容总长度（其他阶段无效）
/// @param len
void AsyncWebServerResponse::setContentLength(size_t len)
{
    if (m_state == RESPONSE_SETUP) {
        m_contentLength = len;
    }
}

/// @brief 在RESPONSE_SETUP阶段设置响应内容类型（其他阶段无效）
/// @param type
void AsyncWebServerResponse::setContentType(const std::string &type)
{
    if (m_state == RESPONSE_SETUP) {
        m_contentType = type;
    }
}

/// @brief 为响应添加头部
/// @param name
/// @param value
void AsyncWebServerResponse::addHeader(const std::string &name, const std::string &value)
{
    m_headers.add(new AsyncWebHeader(name, value));
}

/// @brief 组装HTTP响应的头部信息
/// @param version 协义版本（0对应HTTP/1.0，1对应HTTP/1.1）
/// @return 返回String类型的头部信息
std::string AsyncWebServerResponse::_assembleHead(uint8_t version)
{
    if (version) {
        addHeader("Accept-Ranges", "none"); // 不支持范围请求
        if (m_chunked) {
            addHeader("Transfer-Encoding", "chunked");
        }
    }

    std::string out = std::string();
    int bufSize = 300;
    char buf[bufSize];

    sniprintf(buf, bufSize, "HTTP/1.%d %d %s\r\n", version, m_code, m_responseCodeToString(m_code));
    out.append(buf);

    if (m_sendContentLength) {
        snprintf(buf, bufSize, "Content-Length: %d\r\n", m_contentLength);
        out.append(buf);
    }
    if (m_contentType.length()) {
        snprintf(buf, bufSize, "Content-Type: %s\r\n", m_contentType.c_str());
        out.append(buf);
    }

    for (const auto &header : m_headers) {
        snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str());
        out.append(buf);
    }
    m_headers.free();

    out.append("\r\n");
    m_headLength = out.length();
    return out;
}

/// @brief 检查响应是否已经开始发送
/// @return
bool AsyncWebServerResponse::_started() const
{
    return m_state > RESPONSE_SETUP;
}

/// @brief 检查响应是否已经完成
/// @return
bool AsyncWebServerResponse::_finished() const
{
    return m_state > RESPONSE_WAIT_ACK;
}

/// @brief 检查响应是否失败
/// @return
bool AsyncWebServerResponse::_failed() const
{
    return m_state == RESPONSE_FAILED;
}

/// @brief 验证响应源是否有效
/// @return
bool AsyncWebServerResponse::_sourceValid() const
{
    return false;
}

/// @brief 触发响应并关闭客户端连接
/// @param req
void AsyncWebServerResponse::_respond(AsyncWebServerRequest *req)
{
    m_state = RESPONSE_END;
    req->client()->close();
}

/// @brief 处理客户端对已发送数据的确认（会调用实际的派生类）
/// @param req
/// @param len
/// @param time
/// @return
size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *req, size_t len, uint64_t time)
{
    return 0;
}

/// @brief 构造一个基本的HTTP响应对象
/// @param code
/// @param contentType
/// @param content
AsyncBasicResponse::AsyncBasicResponse(int code, const std::string &contentType, const std::string &content)
{
    m_code = code;
    m_content = content;
    m_contentType = contentType;
    if (m_content.length()) {
        m_contentLength = m_content.length();
        if (!m_contentType.length()) {
            m_contentType = "text/plain";
        }
    }
    addHeader("Connection", "close");
}

/// @brief 将基本响应发送出去........改了部分，不知有没有问题
/// @param req
void AsyncBasicResponse::_respond(AsyncWebServerRequest *req)
{
    m_state = RESPONSE_HEADERS;
    std::string out = _assembleHead(req->version());
    size_t outLen = out.length();
    size_t space = req->client()->get_send_buffer_size();

    if (!m_contentLength) { // 没有响应内容
        if (space >= outLen) {
            m_writtenLength += req->client()->write(out.c_str(), outLen);
            m_state = RESPONSE_WAIT_ACK;
        } else if (space > 0) {
            std::string partial = out.substr(0, space);
            m_content = out.substr(space);
            m_contentLength = outLen - space;
            m_writtenLength += req->client()->write(partial.c_str(), space);
            m_state = RESPONSE_CONTENT;
        } else {
            m_content = out;
            m_contentLength = outLen;
            m_state = RESPONSE_CONTENT;
        }
    } else {                // 存在响应内容
        if (space >= outLen + m_contentLength) {
            out += m_content;
            outLen += m_contentLength;
            m_writtenLength += req->client()->write(out.c_str(), outLen);
            m_state = RESPONSE_WAIT_ACK;
        } else if (space >= outLen) {
            size_t shift = space - outLen;
            outLen += shift;
            out += m_content.substr(0, shift);
            m_sentLength += shift;
            m_content = m_content.substr(shift);
            m_writtenLength += req->client()->write(out.c_str(), outLen);
            m_state = RESPONSE_CONTENT;
        } else if (space > 0) {
            std::string partial = out.substr(0, space);
            m_content = out.substr(space) + m_content;
            m_contentLength += outLen - space;
            m_writtenLength += req->client()->write(partial.c_str(), space);
            m_state = RESPONSE_CONTENT;
        } else {
            m_content = out + m_content;
            m_contentLength += outLen;
            m_state = RESPONSE_CONTENT;
        }
    }
}

/// @brief 接收到客户端确认后发送剩余的响应内容
/// @param req 指向当前请求的指针
/// @param len 最近一次写操作实际发送的数据长度
/// @param time
/// @return
size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *req, size_t len, uint64_t time)
{
    m_ackedLength += len;   // 更新已确认接收的长度
    if (m_state == RESPONSE_CONTENT) {
        size_t space = req->client()->get_send_buffer_size();
        size_t available = m_contentLength - m_sentLength;
        if (space >= available) {
            m_writtenLength += req->client()->write(m_content.c_str(), available);
            m_content.empty();
            m_state = RESPONSE_WAIT_ACK;
            return available;
        } else {
            std::string out = m_content.substr(0, space);
            m_content = m_content.substr(space);
            m_sentLength += space;
            m_writtenLength += req->client()->write(out.c_str(), space);
            return space;
        }
    } else if (m_state == RESPONSE_WAIT_ACK) {
        if (m_ackedLength >= m_writtenLength) {
            m_state = RESPONSE_END;
        }
    }

    return 0;
}

AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor cb)
    : m_callback(cb)
{
    if (cb) {
        m_contentLength = 0;
        m_sendContentLength = 0;
        m_chunked = true;
    }
}

/// @brief 发送异步响应
/// @param req
void AsyncAbstractResponse::_respond(AsyncWebServerRequest *req)
{
    addHeader("Connection", "close");   // 客户端在接收完响应后关闭连接
    m_head = _assembleHead(req->version());
    m_state = RESPONSE_HEADERS;
    _ack(req, 0, 0);
}

/// @brief 确认HTTP响应数据
/// @param req 关联的请求
/// @param len 客户端已确认接收的数据长度
/// @param time
/// @return
size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *req, size_t len, uint64_t time)
{
    if (!_sourceValid()) {
        m_state = RESPONSE_FAILED;
        req->client()->close();
        return 0;
    }

    m_ackedLength += len;
    size_t space = req->client()->get_send_buffer_size();
    size_t headLen = m_head.length();
    if (m_state == RESPONSE_HEADERS) {
        if (space > headLen) {
            m_state = RESPONSE_CONTENT;
            space -= headLen;
        } else {
            std::string out = m_head.substr(0, space);
            m_head = m_head.substr(space);
            m_writtenLength += req->client()->write(out.c_str(), space);
            return space;
        }
    }

    if (m_state == RESPONSE_CONTENT) {
        size_t outLen;
        if (m_chunked) {
            if (space <= 8) {
                return 0;
            }
            outLen = space;
        } else {
            if (m_sendContentLength) {
                size_t requireSize = m_contentLength - m_sentLength;
                outLen = (requireSize > space) ? space : requireSize;
            } else {
                outLen = space;
            }
        }

        auto* buf = new uint8_t[outLen + headLen];
        if (buf == nullptr) {
            // if(headLen) {
            //     m_writtenLength += req->client()->write(m_head.c_str(), headLen);
            //     m_head.clear();
            //     return headLen;
            // }
            return 0;
        }
        if (headLen) {
            memcpy(buf, m_head.c_str(), m_head.length());
        }

        size_t readLen = 0;
        if (m_chunked) {
            readLen = m_fillBufferAndProcessTemplates(buf + headLen + 6, outLen - 8);
            if (readLen == RESPONSE_TRY_AGAIN) {
                delete[] buf;
                return 0;
            }
            outLen = sprintf((char*)buf + headLen, "%04x", readLen) + headLen;
            buf[outLen++] = '\r';
            buf[outLen++] = '\n';
            outLen += readLen;
            buf[outLen++] = '\r';
            buf[outLen++] = '\n';
        } else {
            readLen = m_fillBufferAndProcessTemplates(buf + headLen, outLen);
            if (readLen == RESPONSE_TRY_AGAIN) {
                delete[] buf;
                return 0;
            }
            outLen = readLen + headLen;
        }

        if (headLen) {
            m_head.clear();
        }
        if (outLen) {
            m_writtenLength += req->client()->write((const char*)buf, outLen);
        }

        if (m_chunked) {
            m_sentLength += readLen;
        } else {
            m_sentLength += outLen - headLen;
        }

        delete[] buf;

        if ((m_chunked && readLen == 0) || (!m_sendContentLength && outLen == 0) || (!m_chunked && m_sentLength == m_contentLength)) {
            m_state = RESPONSE_WAIT_ACK;
        }
        return outLen;

    } else if (m_state == RESPONSE_WAIT_ACK) {
        if (!m_sendContentLength || m_ackedLength >= m_writtenLength) {
            m_state = RESPONSE_END;
            if (!m_chunked && !m_sendContentLength) {
                req->client()->close(true);
            }
        }
    }
    return 0;
}

/// @brief 从缓存/内容源（文件等）中读取指定长度数据到缓冲区中
/// @param data 缓冲区
/// @param len 读取的长度
/// @return 返回读取的长度
size_t AsyncAbstractResponse::m_readDataFromCacheOrContent(uint8_t* data, const size_t len)
{
    const size_t readFromCache = std::min(len, m_cache.size());
    if (readFromCache) {
        memcpy(data, m_cache.data(), readFromCache);
        m_cache.erase(m_cache.begin(), m_cache.begin() + readFromCache);
    }
    const size_t needFromFile = len - readFromCache;
    const size_t readFromContent = _fillBuffer(data + readFromCache, needFromFile);
    return readFromCache + readFromContent;
}

/// @brief ...............可以优化
/// @param data
/// @param len
/// @return
size_t AsyncAbstractResponse::m_fillBufferAndProcessTemplates(uint8_t* data, size_t len)
{
    // 没有回调函数>>>不处理模板
    if (!m_callback) {
        return _fillBuffer(data, len);
    }

    const size_t originalLen = len;
    len = m_readDataFromCacheOrContent(data, len);

    uint8_t* pTemplateStart = data;
    while ((pTemplateStart < &data[len]) && (pTemplateStart = (uint8_t *)memchr(pTemplateStart, CONFIG_TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart + 1))) { // data[0] ... data[len - 1]
        uint8_t* pTemplateEnd = (pTemplateStart < &data[len - 1]) ? (uint8_t*)memchr(pTemplateStart + 1, CONFIG_TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart) : nullptr;
        uint8_t buf[CONFIG_TEMPLATE_PARAM_NAME_LENGTH + 1];
        std::string paramName;
        if (pTemplateEnd) {
            const size_t paramNameLength = sizeof(buf) - 1 < pTemplateEnd - pTemplateStart - 1 ? sizeof(buf) - 1 : pTemplateEnd - pTemplateStart - 1;
            if (paramNameLength) {
                memcpy(buf, pTemplateStart + 1, paramNameLength);
                buf[paramNameLength] = 0;
                paramName = std::string(reinterpret_cast<char*>(buf));
            } else { // double percent sign encountered, this is single percent sign escaped.
                memmove(pTemplateEnd, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1);
                len += m_readDataFromCacheOrContent(&data[len - 1], 1) - 1;
                ++pTemplateStart;
            }
        } else if (&data[len - 1] - pTemplateStart + 1 < CONFIG_TEMPLATE_PARAM_NAME_LENGTH + 2) { // closing placeholder not found, check if it's in the remaining file data
            memcpy(buf, pTemplateStart + 1, &data[len - 1] - pTemplateStart);
            const size_t readFromCacheOrContent = m_readDataFromCacheOrContent(buf + (&data[len - 1] - pTemplateStart), CONFIG_TEMPLATE_PARAM_NAME_LENGTH + 2 - (&data[len - 1] - pTemplateStart + 1));
            if (readFromCacheOrContent) {
                pTemplateEnd = (uint8_t*)memchr(buf + (&data[len - 1] - pTemplateStart), CONFIG_TEMPLATE_PLACEHOLDER, readFromCacheOrContent);
                if (pTemplateEnd) {
                    *pTemplateEnd = 0;
                    paramName = std::string(reinterpret_cast<char*>(buf));
                    m_cache.insert(m_cache.begin(), pTemplateEnd + 1, buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent);
                    pTemplateEnd = &data[len - 1];
                } else { // closing placeholder not found in file data, store found percent symbol as is and advance to the next position
                    m_cache.insert(m_cache.begin(), buf + (&data[len - 1] - pTemplateStart), buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent);
                    ++pTemplateStart;
                }
            } else {
                ++pTemplateStart;
            }
        } else {
            ++pTemplateStart;
        }

        if (paramName.length()) {
            const std::string paramValue(m_callback(paramName));
            const char* pvstr = paramValue.c_str();
            const unsigned int pvlen = paramValue.length();
            const size_t numBytesCopied = std::min(pvlen, static_cast<unsigned int>(&data[originalLen - 1] - pTemplateStart + 1));
            // make room for param value
            // 1. move extra data to cache if parameter value is longer than placeholder AND if there is no room to store
            if ((pTemplateEnd + 1 < pTemplateStart + numBytesCopied) && (originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1) < len)) {
                m_cache.insert(m_cache.begin(), &data[originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1)], &data[len]);
                //2. parameter value is longer than placeholder text, push the data after placeholder which not saved into cache further to the end
                memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[originalLen] - pTemplateStart - numBytesCopied);
                len = originalLen; // fix issue with truncated data, not sure if it has any side effects
            } else if (pTemplateEnd + 1 != pTemplateStart + numBytesCopied)
                //2. Either parameter value is shorter than placeholder text OR there is enough free space in buffer to fit.
                //   Move the entire data after the placeholder
            {
                memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1);
            }
            // 3. replace placeholder with actual value
            memcpy(pTemplateStart, pvstr, numBytesCopied);
            // If result is longer than buffer, copy the remainder into cache (this could happen only if placeholder text itself did not fit entirely in buffer)
            if (numBytesCopied < pvlen) {
                m_cache.insert(m_cache.begin(), pvstr + numBytesCopied, pvstr + pvlen);
            } else if (pTemplateStart + numBytesCopied < pTemplateEnd + 1) { // result is copied fully; if result is shorter than placeholder text...
                // there is some free room, fill it from cache
                const size_t roomFreed = pTemplateEnd + 1 - pTemplateStart - numBytesCopied;
                const size_t totalFreeRoom = originalLen - len + roomFreed;
                len += m_readDataFromCacheOrContent(&data[len - roomFreed], totalFreeRoom) - roomFreed;
            } else { // result is copied fully; it is longer than placeholder text
                const size_t roomTaken = pTemplateStart + numBytesCopied - pTemplateEnd - 1;
                len = std::min(len + roomTaken, originalLen);
            }
        }
    }
    return len;
}

AsyncFileResponse::~AsyncFileResponse()
{
    if (m_content != nullptr) {
        fclose(m_content);
    }
}

void AsyncFileResponse::m_setContentType(const std::string &path)
{
    if (path.ends_with(".html")) {
        m_contentType = "text/html";
    } else if (path.ends_with(".htm")) {
        m_contentType = "text/html";
    } else if (path.ends_with(".js")) {
        m_contentType = "application/javascript";
    } else if (path.ends_with(".ico")) {
        m_contentType = "image/x-icon";
    } else if (path.ends_with(".css")) {
        m_contentType = "text/css";
    } else if (path.ends_with(".json")) {
        m_contentType = "application/json";
    } else if (path.ends_with(".png")) {
        m_contentType = "image/png";
    } else if (path.ends_with(".gif")) {
        m_contentType = "image/gif";
    } else if (path.ends_with(".jpg")) {
        m_contentType = "image/jpeg";
    } else if (path.ends_with(".svg")) {
        m_contentType = "image/svg+xml";
    } else if (path.ends_with(".eot")) {
        m_contentType = "font/eot";
    } else if (path.ends_with(".woff")) {
        m_contentType = "font/woff";
    } else if (path.ends_with(".woff2")) {
        m_contentType = "font/woff2";
    } else if (path.ends_with(".ttf")) {
        m_contentType = "font/ttf";
    } else if (path.ends_with(".xml")) {
        m_contentType = "text/xml";
    } else if (path.ends_with(".pdf")) {
        m_contentType = "application/pdf";
    } else if (path.ends_with(".zip")) {
        m_contentType = "application/zip";
    } else if (path.ends_with(".gz")) {
        m_contentType = "application/x-gzip";
    } else {
        m_contentType = "text/plain";
    }
}

/// @brief
/// @param path         请求的文件真实路径
/// @param contentType  请求资源类型
/// @param download     是否为下载模式
/// @param cb           模板处理函数
AsyncFileResponse::AsyncFileResponse(const std::string &path, const std::string &contentType, bool download, AwsTemplateProcessor cb)
    : AsyncAbstractResponse(cb)
{
    m_code = 200;
    m_path = path;

    // 无论压缩与否，内容类型为压缩前文件内容
    if (contentType.empty()) {
        m_setContentType(path);
    } else {
        m_contentType = contentType;
    }

    // 非下载模式，请求的文件不存在但存在压缩版本时
    if (!download && !FILE_EXISTS(m_path.c_str())) {
        m_path += ".gz";
        if (FILE_EXISTS(m_path.c_str())) {
            addHeader("Content-Encoding", "gzip");
            m_callback = nullptr;
            m_sendContentLength = true;
            m_chunked = false;
        }
    }

    struct stat st;
    stat(m_path.c_str(), &st);
    m_contentLength = st.st_size;
    m_content = fopen(m_path.c_str(), "r");

    size_t filenameStart = path.find_last_of('/') + 1;
    const char* filename = path.c_str() + filenameStart;
    size_t bufSize = 26 + path.length() - filenameStart;
    char buf[bufSize];
    if (download) {
        snprintf(buf, bufSize, "attachment; filename=\"%s\"", filename);
    } else {
        snprintf(buf, bufSize, "inline; filename=\"%s\"", filename);
    }
    addHeader("Content-Disposition", buf);
}

/// @brief 读取指定大小的数据量至指定的缓冲区
/// @param data 数据缓冲区
/// @param len 预备读取的数据大小
/// @return 实际读取的数据大小
size_t AsyncFileResponse::_fillBuffer(uint8_t *data, size_t len)
{
    return fread(data, sizeof(uint8_t), len, m_content);
}

AsyncCallbackResponse::AsyncCallbackResponse(const std::string &contentType, size_t len, AwsResponseFiller cb, AwsTemplateProcessor templateCb)
{
    m_code = 200;
    m_content = cb;
    m_contentLength = len;
    if (len == 0) {
        m_sendContentLength = false;
    }
    m_contentType = contentType;
    m_filledLength = 0;
}

size_t AsyncCallbackResponse::_fillBuffer(uint8_t* buf, size_t maxLen)
{
    size_t ret = m_content(buf, maxLen, m_filledLength);
    if (ret != RESPONSE_TRY_AGAIN) {
        m_filledLength += ret;
    }

    return ret;
}

AsyncChunkedResponse::AsyncChunkedResponse(const std::string &contentType, AwsResponseFiller cb, AwsTemplateProcessor templateCb)
{
    m_code = 200;
    m_content = cb;
    m_contentLength = 0;
    m_contentType = contentType;
    m_sendContentLength = false;
    m_chunked = true;
    m_filledLength = 0;
}

size_t AsyncChunkedResponse::_fillBuffer(uint8_t* buf, size_t maxLen)
{
    size_t ret = m_content(buf, maxLen, m_filledLength);
    if (ret != RESPONSE_TRY_AGAIN) {
        m_filledLength += ret;
    }

    return ret;
}

AsyncProgmemResponse::AsyncProgmemResponse(int code, const std::string &contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback)
{
    m_code = code;
    m_content = content;
    m_contentType = contentType;
    m_contentLength = len;
    m_readLength = 0;
}

size_t AsyncProgmemResponse::_fillBuffer(uint8_t *buf, size_t maxLen)
{
    size_t left = m_contentLength - m_readLength;
    if (left > maxLen) {
        memcpy(buf, m_content + m_readLength, maxLen);
        m_readLength += maxLen;
        return maxLen;
    }
    memcpy(buf, m_content + m_readLength, left);
    m_readLength += left;
    return left;
}